package asientos;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.uqbar.commons.utils.Observable;

import colecciones.bloques.BloqueFn;

import colecciones.colecciones.MiColeccion;

import usuarios.Usuario;
import aerolineas.Aerolinea;

import despegar.utiles.Fecha;
import facade.RegistroAsientosComprados;

@Observable
public abstract class Asiento implements Vuelo{
	protected Integer numeroDeAsiento;
	protected String codigoDeVuelo;
	protected BigDecimal precio;
	protected ClaseDeAsiento clase;
	protected UbicacionesAsiento ubicacion;
	protected EstadosAsiento estado;	
	
	protected String horaSalida;
	protected String horaLlegada;
	protected Fecha fechaSalida;
	protected Fecha fechaLlegada;
	
	protected String origen;
	protected String destino;
	
	protected String aerolinea;
	
	List<String> registroReservas = new ArrayList<String>();
	

	
	/* *************************************************
	 * SETTERS
	 **************************************************/
	protected void setOrigen(String origen) {
		this.origen = origen;
	}
	protected void setDestino(String destino) {
		this.destino = destino;
	}
	protected void setFechaDeSalida(Fecha fechaDeSalida) {
		this.fechaSalida = fechaDeSalida;
	}
	protected void setFechaDeLlegada(Fecha fechaDeLlegada) {
		this.fechaLlegada = fechaDeLlegada;
	}
	protected void setHoraDeSalida(String horaDeSalida) {
		this.horaSalida = horaDeSalida;
	}
	protected void setHoraDeLlegada(String horaDeLlegada) {
		this.horaLlegada = horaDeLlegada;
	}
	protected void setCodigoDeVuelo(String codigoDeVuelo) {
		this.codigoDeVuelo = codigoDeVuelo;
	}
	/*
	 * Para poder recargarSegunUsuario en escalas, donde se recarga cada asiento..
	 */
	public void setPrecio(BigDecimal precioOriginal) {
		this.precio = precioOriginal;
	}
	protected void  setClase(ClaseDeAsiento clase) {
		this.clase = clase;
	}
	protected void setUbicacion(UbicacionesAsiento ubicacion) {
		this.ubicacion = ubicacion;
	}
	protected void setEstado(EstadosAsiento estado) {
		this.estado = estado;
	}
	protected void setNumeroDeAsiento(Integer numeroDeAsiento) {
		this.numeroDeAsiento = numeroDeAsiento;
	}
	/* ***********************************
	 * API
	 ************************************/
	@Override
	public String getCodigoDeVuelo() {
		return this.codigoDeVuelo;
	}
	@Override
	public BigDecimal getPrecio() {
		return this.precio;
	}
	@Override
	public boolean esSuperOferta() {
		return this.clase.esSuperOferta(this);
	}
	@Override
	public void recargarSegunUsuario(Usuario unUsuario, int unRecargo) {
		if(!unUsuario.tieneCuentaPaga()) {
			this.precio=this.getPrecio().add(new BigDecimal(unRecargo));
		}
	}
	@Override
	public UbicacionesAsiento getUbicacion() {
		return this.ubicacion;
	}
	@Override
	public boolean sosDeLaAerolinea(Aerolinea unaAerolinea) {
		return this.sosDeLaAerolinea(unaAerolinea.getNombre());
	}
	@Override
	public String getOrigen() {
		return this.origen;
	}
	@Override
	public String getDestino() {
		return this.destino;
	}
	@Override
	public Fecha getFechaSalida() {
		return this.fechaSalida;
	}
	@Override
	public Fecha getFechaLlegada() {
		return this.fechaLlegada;
	}
	@Override
	public String getHoraSalida() {
		return this.horaSalida;
	}
	@Override
	public String getHoraLlegada() {
		return this.horaLlegada;
	}
	@Override
	public double getTiempoDeVuelo() {
		return this.fechaLlegada.plus(this.horaLlegada).diferenciaCon(this.fechaSalida.plus(this.horaSalida));
	}
	@Override
	public double getPopularidad(){
		return RegistroAsientosComprados.getInstance().getCantidadDeVuelosComprados(this.getCodigoDeVuelo());
	}
	@Override
	public EstadosAsiento getEstado() {
		return this.estado;
	}
	@Override
	public boolean estaLibre() {
		return this.getEstado().equals(EstadosAsiento.DISPONIBLE);
	}
	public boolean equals(Asiento otroAsiento) {
		return
			this.getCodigoDeVuelo().equals(otroAsiento.getCodigoDeVuelo())
			&& this.getNumeroDeAsiento().equals(otroAsiento.getNumeroDeAsiento());
	}
	public Integer getNumeroDeAsiento() {
		return this.numeroDeAsiento;
	}
	@Override
	public void registrarCompra() {
		RegistroAsientosComprados.getInstance().registrarCompra(this.getCodigoDeVuelo());		
	}
	@Override
	public List<String> getClasesDeAsientos() {
		return new MiColeccion<ClaseDeAsiento>()
			.addAll(this.getClasesDeAsientosClase())	
			.map(new BloqueFn<ClaseDeAsiento, String>() {
				@Override
				public String fn(ClaseDeAsiento claseDeAsiento) {
					return claseDeAsiento.getNombre();
				}
			}).asArrayList();
	}
	@Override
	public ClaseDeAsiento getClase() {
		return this.clase;
	}
	/* ***********************
	 * ABSTRACTS
	 ************************/
	public abstract boolean sosDeLaAerolinea(String nombreDeLaAerolinea);
	@Override
	public String getAerolinea() {
		return this.getAerolinea();
	}
	protected List<ClaseDeAsiento> getClasesDeAsientosClase() {
		List<ClaseDeAsiento> clasesDeAsiento = new ArrayList<ClaseDeAsiento>();
		clasesDeAsiento.add(this.getClase());
		return(clasesDeAsiento);
	}//HAGO ESTE METODO PARA PODER ARTICULAR EL FILTRO OPCIONAL POR CLASE DE ASIENTO CON LAS ESCALAS, LAS CUALES COMO VAN A ESTAR CONSTITUIDAS CON VARIOS ASIENTOS LOS CUALES PUEDEN LLEGAR A TENER DISTINTAS CLASES, VAN A DEVOLVER UNA LISTA CON TODAS ESTAS CLASES

	public void registrarReserva(String dniDelUsuarioQueReservo){
		this.registroReservas.add(dniDelUsuarioQueReservo);
	}
}
